# -*- coding: utf-8 -*-

import sys
import pygame
from pygame.locals import *


SIZE = 30  # 棋盘每个点的距离
LINES = 19  # 棋盘的行/列数
OUTER_WIDTH = 20  # 棋盘外宽度
INSIDE_WIDTH = 4  # 边框与棋盘最外的小间隔
BORDER_WIDTH = 4  # 边框宽度
BORDER_LENGTH = SIZE*(LINES - 1) + INSIDE_WIDTH*2 + BORDER_WIDTH  # 边框线长度
START_X = START_Y = OUTER_WIDTH + int(BORDER_WIDTH/2) + INSIDE_WIDTH  # 边框左上角坐标
SCREEN_WIDTH = SCREEN_HEIGHT = SIZE*(LINES - 1) + OUTER_WIDTH*2 + BORDER_WIDTH + INSIDE_WIDTH*2  # 屏幕高度
# SCREEN_WIDTH = SCREEN_HEIGHT + 200  # 游戏屏幕的宽

STONE_R = SIZE//2 - 3  # 棋子半径
# STONE_R2 = SIZE//2 + 3

# BOARD_COLOR = (0xE3, 0x92, 0x65)  # 背景颜色
BOARD_COLOR = (0xFA, 0xBE, 0x6E)  # 背景颜色
BLACK_COLOR = (0, 0, 0)  # 黑色
WHITE_COLOR = (255, 255, 255)  # 白色
RED_COLOR = (200, 30, 30)  # 红色
# BLUE_COLOR = (30, 30, 200)  # 蓝色


# 黑子或者白子，value = 1为黑，2为白
class Chessman:
    def __init__(self, name, value, color):
        self.name = name
        self.value = value
        self.color = color
        pass
    pass


# 游戏坐标系，左上角为(0，0)，最大为(LINES - 1, LINES - 1)
class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
        pass
    pass


BLACK_CHESSMAN = Chessman('black', 1, (45, 45, 45))
WHITE_CHESSMAN = Chessman('white', 2, (219, 219, 219))

# 偏移量
offset = [(1, 0), (0, 1), (1, 1), (1, -1)]


# 棋盘
class Board:
    def __init__(self, lines):
        self._lines = lines
        self._board = [[0] * lines for _ in range(lines)]  # 矩阵[LINESxLINES]
        pass

    def getBoard(self):
        return self._board

    def setBoard(self, new_board):
        self._board = new_board
        pass

    def canDrop(self, point):
        return self._board[point.y][point.x] == 0

    def drop(self, chessman, point):
        self._board[point.y][point.x] = chessman.value
        # for row in self._board:
        #     print(row)
        #     pass
        # print('---------------------------------------------------------')

        if self.win(point):
            print(f'{chessman.name} win, (Press SPACE to continue...)')
            return chessman
        pass

    def win(self, point):
        cur_value = self._board[point.y][point.x]
        for item in offset:
            if self.getCountOnDirection(point, cur_value, item[0], item[1]) >= 5:
                return True
            pass
        pass

    def getCountOnDirection(self, point, value, x_offset, y_offset):
        count = 1
        for step in range(1, 5):
            x = point.x + step*x_offset
            y = point.y + step*y_offset
            if 0 <= x < self._lines and 0 <= y < self._lines and self._board[y][x] == value:
                count += 1
            else:
                break
                pass
            pass

        for step in range(1, 5):
            x = point.x - step*x_offset
            y = point.y - step*y_offset
            if 0 <= x < self._lines and 0 <= y < self._lines and self._board[y][x] == value:
                count += 1
            else:
                break
                pass
            pass

        return count

    pass


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption('欢乐五子棋')

    font1 = pygame.font.SysFont('SimHei', 32)  # 黑体32
    font2 = pygame.font.SysFont('SimHei', 72)  # 黑体72
    f1width, f1height = font2.size('黑子获胜')
    f2width, f2height = font1.size('Press SPACE to continue...')

    board = Board(LINES)
    cur_runner = BLACK_CHESSMAN
    winner = None

    while True:
        for event in pygame.event.get():
            # “退出”事件
            if event.type == QUIT:
                sys.exit()
            elif event.type == KEYDOWN:
                # 空格按下
                if event.key == K_SPACE:
                    if winner is not None:
                        winner = None
                        cur_runner = BLACK_CHESSMAN
                        board = Board(LINES)
                        pass
                    pass
                pass
            elif event.type == MOUSEBUTTONDOWN:
                if winner is None:
                    pressed_array = pygame.mouse.get_pressed(3)
                    # 左键按下
                    if pressed_array[0]:
                        mouse_pos = pygame.mouse.get_pos()
                        click_point = getClickPoint(mouse_pos)
                        if click_point is not None:
                            if board.canDrop(click_point):
                                winner = board.drop(cur_runner, click_point)
                                if winner is None:
                                    cur_runner = getNextRunner(cur_runner)
                                    pass
                                pass
                            pass
                        else:
                            print('超过棋盘范围...')
                            pass
                        pass
                    pass
                pass
            pass

        # 画棋盘
        drawBoard(screen)
        # 画棋子
        drawStones(board, screen)

        # 结算界面
        if winner:
            print_text(screen, font2, (SCREEN_WIDTH - f1width)//2, (SCREEN_HEIGHT - f1height)//2 - f2height,
                       winner.name + '获胜', RED_COLOR)
            print_text(screen, font1, (SCREEN_WIDTH - f2width)//2, (SCREEN_HEIGHT - f1height)//2 + 2*f2height,
                       "Press SPACE to continue...", RED_COLOR)

        pygame.display.flip()
        pass
    pass


def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
    imgText = font.render(text, True, fcolor)
    screen.blit(imgText, (x, y))
    pass


def drawBoard(screen):
    # 填充颜色
    screen.fill(BOARD_COLOR)
    # 画外边框
    pygame.draw.rect(screen, BLACK_COLOR, (OUTER_WIDTH, OUTER_WIDTH, BORDER_LENGTH, BORDER_LENGTH), BORDER_WIDTH)
    # 画网格线
    # 水平
    for i in range(LINES):
        pygame.draw.line(screen, BLACK_COLOR,
                         (START_X, START_Y + SIZE*i),
                         (START_X + SIZE*(LINES - 1), START_Y + SIZE*i),
                         1)
        pass
    # 垂直
    for j in range(LINES):
        pygame.draw.line(screen, BLACK_COLOR,
                         (START_X + SIZE*j, START_Y),
                         (START_X + SIZE*j, START_Y + SIZE*(LINES - 1)),
                         1)
        pass
    # 画点
    for i in (3, 9, 15):
        for j in (3, 9, 15):
            if i == j == 9:
                r = 5
            else:
                r = 3
                pass
            pygame.draw.circle(screen, BLACK_COLOR, (START_X + SIZE*i, START_Y + SIZE*j), r, 0)
            pass
        pass
    pass


def drawStones(board, screen):
    for i, row in enumerate(board.getBoard()):
        for j, cell in enumerate(row):
            if cell == BLACK_CHESSMAN.value:
                drawStone(screen, Point(j, i), BLACK_CHESSMAN.color)
            elif cell == WHITE_CHESSMAN.value:
                drawStone(screen, Point(j, i), WHITE_CHESSMAN.color)
                pass
            pass
        pass
    pass


def drawStone(screen, point, stone_color):
    pygame.draw.circle(screen, stone_color, (START_X + SIZE*point.x, START_Y + SIZE*point.y), STONE_R, 0)
    pass


def getClickPoint(click_pos):
    pos_x = click_pos[0] - START_X
    pos_y = click_pos[1] - START_Y
    if pos_x < -INSIDE_WIDTH or pos_y < -INSIDE_WIDTH:
        return None
    x = pos_x//SIZE
    y = pos_y//SIZE
    if pos_x % SIZE > SIZE/2:
        x += 1
        pass
    if pos_y % SIZE > SIZE/2:
        y += 1
        pass
    if x >= LINES or y >= LINES:
        return None

    return Point(x, y)
    pass


def getNextRunner(cur_runner):
    if cur_runner == BLACK_CHESSMAN:
        return WHITE_CHESSMAN
    else:
        return BLACK_CHESSMAN
    pass


if __name__ == '__main__':
    main()
    pass
